#include "file_manager.h"

// 删除文件
int remove_file(const char *path) {
    if (remove(path) == 0) {
        printf("文件删除成功: %s\n", path);
        return 0;
    } else {
        printf("文件删除失败: %s\n", strerror(errno));
        return -1;
    }
}

// 使用标准IO复制文件
int copy_file_stdio(const char *src_path, const char *dest_path) {
    FILE *src_file, *dest_file;
    char buffer[BUFFER_SIZE];
    size_t bytes_read;
    int src_fd, dest_fd;
    struct stat stat_buf;
    
    // 先检查源文件是否被锁定
    if (file_is_locked(src_path)) {
        printf("警告: 源文件可能已被其他进程锁定\n");
    }
    
    src_file = fopen(src_path, "rb");
    if (src_file == NULL) {
        printf("无法打开源文件: %s\n", strerror(errno));
        return -1;
    }
    
    dest_file = fopen(dest_path, "wb");
    if (dest_file == NULL) {
        printf("无法创建目标文件: %s\n", strerror(errno));
        fclose(src_file);
        return -1;
    }
    
    // 获取文件描述符并加锁
    src_fd = fileno(src_file);
    dest_fd = fileno(dest_file);
    
    if (lock_file(src_fd, LOCK_READ) == -1) {
        fclose(src_file);
        fclose(dest_file);
        return -1;
    }
    
    if (lock_file(dest_fd, LOCK_WRITE) == -1) {
        unlock_file(src_fd);
        fclose(src_file);
        fclose(dest_file);
        return -1;
    }
    
    printf("使用标准IO复制文件...\n");
    while ((bytes_read = fread(buffer, 1, BUFFER_SIZE, src_file)) > 0) {
        if (fwrite(buffer, 1, bytes_read, dest_file) != bytes_read) {
            printf("写入失败\n");
            unlock_file(src_fd);
            unlock_file(dest_fd);
            fclose(src_file);
            fclose(dest_file);
            return -1;
        }
    }
    
    // 解锁文件
    unlock_file(src_fd);
    unlock_file(dest_fd);
    fclose(src_file);
    fclose(dest_file);
    printf("文件复制成功: %s -> %s\n", src_path, dest_path);
    return 0;
}

// 使用系统IO复制文件
int copy_file_sysio(const char *src_path, const char *dest_path) {
    int src_fd, dest_fd;
    ssize_t bytes_read, bytes_written;
    char buffer[BUFFER_SIZE];
    struct stat stat_buf;
    
    // 先检查源文件是否被锁定
    if (file_is_locked(src_path)) {
        printf("警告: 源文件可能已被其他进程锁定\n");
    }
    
    src_fd = open(src_path, O_RDONLY);
    if (src_fd == -1) {
        printf("无法打开源文件: %s\n", strerror(errno));
        return -1;
    }
    
    // 对源文件加读锁
    if (lock_file(src_fd, LOCK_READ) == -1) {
        close(src_fd);
        return -1;
    }
    
    // 获取源文件权限
    if (fstat(src_fd, &stat_buf) == -1) {
        printf("无法获取源文件信息\n");
        unlock_file(src_fd);
        close(src_fd);
        return -1;
    }
    
    dest_fd = open(dest_path, O_WRONLY | O_CREAT | O_TRUNC, stat_buf.st_mode);
    if (dest_fd == -1) {
        printf("无法创建目标文件: %s\n", strerror(errno));
        unlock_file(src_fd);
        close(src_fd);
        return -1;
    }
    
    // 对目标文件加写锁
    if (lock_file(dest_fd, LOCK_WRITE) == -1) {
        unlock_file(src_fd);
        close(src_fd);
        close(dest_fd);
        return -1;
    }
    
    printf("使用系统IO复制文件...\n");
    while ((bytes_read = read(src_fd, buffer, BUFFER_SIZE)) > 0) {
        bytes_written = write(dest_fd, buffer, bytes_read);
        if (bytes_written != bytes_read) {
            printf("写入失败\n");
            unlock_file(src_fd);
            unlock_file(dest_fd);
            close(src_fd);
            close(dest_fd);
            return -1;
        }
    }
    
    if (bytes_read == -1) {
        printf("读取失败\n");
        unlock_file(src_fd);
        unlock_file(dest_fd);
        close(src_fd);
        close(dest_fd);
        return -1;
    }
    
    // 解锁文件
    unlock_file(src_fd);
    unlock_file(dest_fd);
    close(src_fd);
    close(dest_fd);
    printf("文件复制成功: %s -> %s\n", src_path, dest_path);
    return 0;
}

// 查看文件内容
int view_file(const char *path) {
    FILE *file;
    char buffer[BUFFER_SIZE];
    int fd;
    
    // 先检查文件是否被锁定
    if (file_is_locked(path)) {
        printf("警告: 文件可能已被其他进程锁定\n");
    }
    
    file = fopen(path, "r");
    if (file == NULL) {
        printf("无法打开文件: %s\n", strerror(errno));
        return -1;
    }
    
    // 获取文件描述符并加读锁
    fd = fileno(file);
    if (lock_file(fd, LOCK_READ) == -1) {
        fclose(file);
        return -1;
    }
    
    printf("文件内容: %s\n", path);
    printf("--------------------------------\n");
    
    while (fgets(buffer, BUFFER_SIZE, file) != NULL) {
        printf("%s", buffer);
    }
    
    printf("--------------------------------\n");
    // 解锁文件
    unlock_file(fd);
    fclose(file);
    return 0;
}

// 创建新文件
int create_file(const char *path) {
    FILE *file;
    
    file = fopen(path, "w");
    if (file == NULL) {
        printf("无法创建文件: %s\n", strerror(errno));
        return -1;
    }
    
    fclose(file);
    printf("文件创建成功: %s\n", path);
    return 0;
}

// 写入内容到文件
int write_to_file(const char *path, const char *content, int keep_lock) {
    FILE *file;
    int fd;
    
    // 先检查文件是否被锁定
    if (file_is_locked(path)) {
        printf("警告: 文件可能已被其他进程锁定\n");
    }
    
    file = fopen(path, "w");
    if (file == NULL) {
        printf("无法打开文件: %s\n", strerror(errno));
        return -1;
    }
    
    // 获取文件描述符并加锁
    fd = fileno(file);
    if (lock_file(fd, LOCK_WRITE) == -1) {
        fclose(file);
        return -1;
    }
    
    if (fputs(content, file) == EOF) {
        printf("写入失败\n");
        unlock_file(fd);
        fclose(file);
        return -1;
    }
    
    // 刷新缓冲区以确保内容写入磁盘
    fflush(file);
    
    // 如果不需要保持锁，则解锁并关闭文件
    if (!keep_lock) {
        unlock_file(fd);
        fclose(file);
        printf("内容写入成功: %s\n", path);
    } else {
        // 检查是否还有空间存储锁定文件信息
        if (num_locked_files >= MAX_LOCKED_FILES) {
            printf("警告: 已达到最大锁定文件数量，无法保持文件锁定\n");
            unlock_file(fd);
            fclose(file);
            return -1;
        }
        
        // 存储锁定文件信息到全局数组
        strncpy(locked_files[num_locked_files].path, path, sizeof(locked_files[num_locked_files].path) - 1);
        locked_files[num_locked_files].file = file;
        locked_files[num_locked_files].fd = fd;
        num_locked_files++;
        
        printf("内容写入成功，文件已加锁并保持打开状态\n");
        printf("提示: 可以使用'unlock'命令手动解锁，或退出程序时自动解锁\n");
    }
    
    return 0;
}